#include "abs_factory/Tray.h"
#include "abs_factory/Page.h"
#include "abs_factory/Factory.h"
#include "list_factory/Factory.h"
#include "list_factory/ListLink.h"
#include "list_factory/ListTray.h"
#include "list_factory/ListPage.h"
#include "table_factory/TableLink.h"
#include "table_factory/TableTray.h"
#include "table_factory/TablePage.h"
#include "table_factory/Factory.h"
#include <iostream>
#include <fstream>
/////////////////////////////////////
/// @brief AbsFactory::Tray implementation
/////////////////////////////////////

void AbsFactory::Tray::add(const Item* item)
{
    tray.push_back(item);
}


/////////////////////////////////////
/// @brief AbsFactory::Page implementation
/////////////////////////////////////

void AbsFactory::Page::add(const std::shared_ptr<AbsFactory::Item> item)
{
    content.push_back(item);
}

void AbsFactory::Page::output()
{
    std::string filename = title + ".html";
    std::ofstream ofs(filename);
    if(ofs.fail())
    {
        std::cerr << "Failed to open file: " << filename << std::endl;
        return;
    }
    ofs << this->makeHTML(); // explicitly call the local version of makeHTML
    ofs.close();
}


/////////////////////////////////////
/// @brief ListFactory::ListLink implementation
/////////////////////////////////////

std::string ListFactory::ListLink::makeHTML() const
{
    return  "<li><a href=\"" + url + "\">" + caption + "</a></li>\n";
}

////////////////////////////////////
/// @brief ListFactory::Listtray implementation
////////////////////////////////////

std::string ListFactory::ListTray::makeHTML() const
{
    std::string buffer;
    buffer += "<li>\n";
    buffer += caption + "\n";
    buffer += "<ul>\n";

    auto iter = tray.begin();
    while(iter != tray.end())
    {
        const AbsFactory::Item* item = *iter;
        buffer += item->makeHTML();
        iter++;
    }

    buffer += "</ul>\n";
    buffer += "</li>\n";
    return buffer;
}

////////////////////////////////////
/// @brief ListFactory::ListPage implementation
////////////////////////////////////

std::string ListFactory::ListPage::makeHTML() const
{
    std::string buffer;
    buffer += "<html><head><title>" + title + "</title></head>\n";
    buffer += "<body>\n";
    buffer += "<h1>" + title + "</h1>\n";
    buffer += "<ul>\n";

    auto iter = content.begin();
    while(iter != content.end())
    {
        auto item = *iter;
        buffer += item->makeHTML();
        iter++;
    }
    buffer += "</ul>\n";
    buffer += "<hr><address>" + author + "</address>\n";
    buffer += "</body>\n";
    buffer += "</html>\n";
    return buffer;
}


////////////////////////////////////
/// @brief ListFactory::Factory implementation
////////////////////////////////////

std::shared_ptr<AbsFactory::Tray> ListFactory::Factory::createTray(std::string caption)
{
    return std::make_shared<ListFactory::ListTray>(caption);
}

std::shared_ptr<AbsFactory::Link> ListFactory::Factory::createLink(std::string caption, std::string url)
{
    return std::make_shared<ListFactory::ListLink>(caption, url);
}

std::shared_ptr<AbsFactory::Page> ListFactory::Factory::createPage(std::string title, std::string author)
{
    return std::make_shared<ListFactory::ListPage>(title, author);
}



////////////////////////////////////
/// @brief TableFactory::TableLink implementation
////////////////////////////////////
std::string TableFactory::TableLink::makeHTML() const
{
    return "<td><a href=\"" + url + "\">" + caption + "</a></td>\n";
}


////////////////////////////////////
/// @brief TableFactory::TableTray implementation
////////////////////////////////////

std::string TableFactory::TableTray::makeHTML() const
{
    std::string buffer;
    // create table header
    buffer += "<td>\n";
    buffer += "<table width=\"100%\" border=\"1\"><tr>";

    // create title row
    buffer += "<td bgcolor=\"#cccccc\" align=\"center\" colspan=\"" + tray.size();
    buffer += "\"><b>" + caption + "</b></td>\n";
    // create item rows
    buffer += "</tr>\n";
    buffer += "<tr>\n";

    std::vector<const Item*>::const_iterator citer = tray.begin();
    while (citer != tray.end())
    {
        buffer += (*citer)->makeHTML();
        citer++;
    }

    // create table footer
    buffer += "</tr></table>\n";
    buffer += "</td>\n";
    return buffer;
}


////////////////////////////////////
/// @brief TableFactory::TablePage implementation
////////////////////////////////////
std::string TableFactory::TablePage::makeHTML() const 
{
    std::string buffer;
    // create header 
    buffer += "<html><head><title>" + title + "</title></head>\n";
    buffer += "<body>\n";
    buffer += "<h1>" + title + "</h1>\n";

    // create table
    buffer += "<table width=\"80%\" border=\"3\">\n";
    auto iter = content.begin();
    while(iter != content.end())
    {
        buffer += (*iter)->makeHTML();
        iter++;
    }
    buffer += "</table>\n";
    
    // create footer
    buffer += "<hr><address>" + author + "</address>\n";
    buffer += "</body>\n";
    buffer += "</html>\n";
    return buffer; 
}


////////////////////////////////////
/// @brief TableFactory::Factory implementation
////////////////////////////////////

std::shared_ptr<AbsFactory::Tray> TableFactory::Factory::createTray(std::string caption)
{
    return std::make_shared<TableFactory::TableTray>(caption);
}

std::shared_ptr<AbsFactory::Link> TableFactory::Factory::createLink(std::string caption, std::string url)
{
    return std::make_shared<TableFactory::TableLink>(caption, url);
}

std::shared_ptr<AbsFactory::Page> TableFactory::Factory::createPage(std::string title, std::string author)
{
    return std::make_shared<TableFactory::TablePage>(title, author);
}